package com.parking.common.web.aop;

import com.parking.common.core.exception.PermissionException;
import com.parking.common.core.model.RedisKey;
import com.parking.common.core.util.JwtUtil;
import com.parking.common.web.util.RedisUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.checkerframework.framework.qual.AnnotatedFor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.logging.Handler;

@Component
@Aspect
public class PermissionAop {
    @Resource
    private RedisUtil redisUtil;

    @Pointcut("@annotation(com.parking.common.web.aop.Permission)")
    public void  pt(){
    }
    @Around("pt()") //环绕通知
    public Object PermissionControl(ProceedingJoinPoint pjp) throws Throwable {
        // 1.获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String token = request.getHeader("authorization");
        if (!StringUtils.hasLength(token)) {
            throw new PermissionException("未认证", 1001);
        }
        // 2.获取权限
        Integer platformId = JwtUtil.getPlatformId(token);
        Set<String> set = redisUtil.members(RedisKey.platformRoleInterface(platformId.toString()));
        String roleName = redisUtil.get(RedisKey.platformRole(platformId.toString()));
        // 3.获取切入点方法，基于切入点方法上的注解的值去进行比对，
        // 如果比对成功，执行切入点方法，
        // 如果比对失败，就表示没有权限访问对应的切入点方法，抛出异常处理
        // 获取切入点方法对象
        Signature signature = pjp.getSignature();
        MethodSignature ms = (MethodSignature) signature;
        Method method = ms.getMethod();
        // 获取切入点方法的参数列表
        Object[] args = pjp.getArgs();
        Object value = null;
        // 如果切入点方法上存在Permission注解，表示访问该方法需要进行权限控制
        if (method.isAnnotationPresent(Permission.class)) {
            Permission permission = method.getAnnotation(Permission.class);
            String[] roles = permission.roles();
            String[] resources = permission.resources();
            // 默认情况，只需要认证，不需要授权
            if (roles.length == 0 && resources.length == 0) {
                value = pjp.proceed(args);
            } else {
                boolean hasPermission = false;
                // 遍历资源名称，判断是否有权限
                for (String resource : resources) {
                    if (set.contains(resource)) {
                        hasPermission = true;
                        break;
                    }
                }
                // 判断角色
                if (hasPermission) {
                    for (String role : roles) {
                        if (role.equals(roleName)) {
                            System.out.println(roleName);
                            System.out.println(role);
                            System.out.println(role.equals(roleName));
                            hasPermission = true;
                            break;
                        } else {
                            hasPermission = false;
                        }
                    }
                }
                if (hasPermission) {
                    value = pjp.proceed(args);
                } else {
                    throw new PermissionException("没有权限", 403);
                }
            }
        }
        return value;
    }
}
